<template>
    <div class="main_box">
        <h1>这个案例主要是 vue3的 ref/reactive/computed的 Typescript写法</h1>

        <div class="main_row" ref="rowRef">具体用法见组件内代码</div>
        <TeDemo1Son ref="sonRef" @update1="updateSonData" />
    </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, useTemplateRef, onMounted } from 'vue';
import TeDemo1Son from './teDemo1Son.vue';

// vue3+ts 有很多内置的Typescript类型,比如MouseEvent、HTMLElement、Date、Promise等

interface MyUser {
    name: string;
    age: number;
    sex?: string;
}

// 1.约定ref绑定的类型
const numRef = ref<number>(0); // 基础类型的ref,直接指定类型即可
const dateRef = ref<Date>(new Date()); // 日期类型的ref
const Times = ref<number | null>(null); // 联合类型的ref(比如计时器)

const arrayRef = ref<MyUser[]>([]); // 数组类型的ref,(指定数组元素类型)
const array2Ref = ref<Array<any>>([]); // 数组类型的ref,(不指定数组元素类型)

const objRef = ref<MyUser>({ name: '李四', age: 20 }); // 对象类型的ref,(指定对象格式)
const obj2Ref = ref<object>({ name: '李四', age: 20 }); // 对象类型的ref,(不指定对象格式)

const domRef = ref<HTMLElement | null>(null); // dom类型的ref,需要加上联合类型null,处理未挂载的情况
const ipuRef = ref<HTMLInputElement | null>(null); // input类型的ref,需要加上联合类型null,处理未挂载的情况(还有HTMLDivElement、HTMLVideoElement等)

const mouseRef = ref<MouseEvent | null>(null); // 鼠标事件类型的ref,需要加上联合类型null,处理未触发的情况
const promiseRef = ref<Promise<any> | null>(null); // Promise类型的ref,需要加上联合类型null,处理未赋值的情况

const rowRef = useTemplateRef<HTMLElement>('rowRef'); // vue3.5+新特性，模板ref,不需要加联合类型null

type ChildComType = InstanceType<typeof TeDemo1Son>; // 获取子组件的类型
const sonRef = useTemplateRef<ChildComType>('sonRef'); // 子组件的ref,指定子组件的类型(有子组件的实例方法和属性提醒)

const updateSonData = (data: string) => {
    console.log(data);
};

onMounted(() => {
    // console.log(sonRef.value?.sonData);
    // console.log(sonRef.value?.sonMethod(1));
});

// 2.约定reactive绑定的类型
const activeUser = reactive<MyUser>({
    name: '张三',
    age: 18
}); // reactive绑定对象(interface接口解决数据格式复用问题)

const userList = reactive<MyUser[]>([]); // reactive绑定数组

// 3.约定computed返回的类型
const userCount = computed<number>(() => {
    return userList.filter(item => item.sex === '男').length;
});
</script>

<style lang="scss" scoped></style>
